---@module mqttInMsg
--- 模块功能：MQTT客户端数据接收处理
-- @author openLuat
-- @module mqtt.mqttInMsg
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28
require "tool"
require "hwMqttCmdHandle"
require "mqttOutMsg"
require "serviceConfig"
module(..., package.seeall)

-- 推送系统信息的回调函数(只一次)
local function hwpubCb(result)
    log.info("hwpubCb", result)
    -- if result then sys.timerStart(pubQos1Test,10000) end
end

-- 处理华为云平台端向设备下发的设备属性配置
-- {"services":[{"properties":{"alarmlevel":10,"alarmdistance":10},"service_id":"sensor"}]}
local function handlePropSet(tb)
    for i = 1, #tb["services"] do
        local service = tb["services"][i]
        local service_id = service["service_id"]
        -- 对应到deviceConfig里面的一级对象
        local s = (serviceConfig.getData())[service_id]
        if s ~= nil then
            -- 遍历需要修改的值
            local properties = service["properties"]
            for k, v in pairs(properties) do s[k] = v end
        end
    end
    -- 保存
    serviceConfig.save();
    -- 马上推送一次service
    mqttOutMsg.sendHwService(false)
end

-- 处理华为云平台端主动想设备获取属性配置
-- {
--    "object_device_id": "{object_device_id}",
--    "service_id": "Temperature"
-- }
local function handlePropGet(tb)
    local service_id = tb["service_id"]
    local s = (serviceConfig.getData())[service_id]
    return service_id, s
end

--- MQTT客户端数据接收处理
-- @param mqttClient，MQTT客户端对象
-- @return 处理成功返回true，处理出错返回false
-- @usage mqttInMsg.proc(mqttClient)
function proc(mqttClient)
    local result, data
    while true do
        result, data = mqttClient:receive(60000, "APP_SOCKET_SEND_DATA")
        -- 接收到数据
        if result then
            log.info("mqttInMsg.proc hex", data.topic,
                     string.toHex(data.payload))
            log.info("mqttInMsg.proc string", data.topic, data.payload)

            -- 命令响应
            -- $oc/devices/6084b8353dc5a602c06a61e0_867435056932106/sys/commands/request_id=f6aa213b-7e5e-4e5c-a5f3-f
            -- {"paras":{"direction":"forward","runtime":2000},"service_id":"base","command_name":"CMD_MOTORGO"}
            if string.find(data.topic, _G.MQTT_TOPIC_COMMANDS_REQ) then
                -- 以request_id 分割
                local arr, n = tool.strSplit(data.topic, 'request_id=')
                -- 避免$oc/devices/{device_id}/sys/commands/response/request_id={request_id}
                if n == 2 and arr[1] == _G.MQTT_TOPIC_COMMANDS_REQ then
                    local requestId = arr[2]
                    -- 真的是这个topic
                    local payloadTb, ok = json.decode(data.payload)
                    if ok == true then
                        -- 处理
                        if payloadTb["command_name"] ~= "CMD_HEX" then
                            local re = hwMqttCmdHandle.handleCmd(
                                           payloadTb["command_name"],
                                           payloadTb["paras"])
                            -- 发送
                            -- 通过mqtt发送出去
                            local reTb = {["result_code"] = 0, ["paras"] = re}
                            mqttOutMsg.insertMsg2Json(
                                _G.MQTT_TOPIC_COMMANDS_REQ ..
                                    'response/request_id=' .. requestId, reTb,
                                0, {cb = hwpubCb})
                        else
                            local data = payloadTb["paras"]["hexData"]
                            local result, cmd_buf = "", ""
                            local re = ""
                            sys.taskInit(function()
                                uart485.modbusSend(string.fromHex(data))
                                -- sys.wait(3000)
                                result, cmd_buf = sys.waitUntil(
                                                      "MY_UART_REC_DAT", 3000)
                                if result then
                                    re = {["code"] = 0, ["msg"] = string.toHex(cmd_buf)}
                                else
                                    re = {["code"] = 3, ["msg"] = "fail"}
                                end

                                local reTb = {
                                    ["result_code"] = 0,
                                    ["paras"] = re
                                }
                                mqttOutMsg.insertMsg2Json(
                                    _G.MQTT_TOPIC_COMMANDS_REQ ..
                                        'response/request_id=' .. requestId,
                                    reTb, 0, {cb = hwpubCb})
                            end)
                        end

                    end
                end
            end

            -- 平台端属性下发
            -- {"services":[{"properties":{"alarmlevel":10,"alarmdistance":10},"service_id":"sensor"}]}
            -- $oc/devices/609e4a14bbe12002c07d479f_867435056932106/sys/properties/set/request_id=154d7877-3632-49
            if string.find(data.topic, _G.MQTT_TOPIC_PROSET_REQ) then
                -- 以request_id 分割
                local arr, n = tool.strSplit(data.topic, 'request_id=')
                -- $oc/devices/{device_id}/sys/properties/set/response/request_id={request_id}
                if n == 2 and arr[1] == _G.MQTT_TOPIC_PROSET_REQ then
                    local requestId = arr[2]
                    -- 真的是这个topic
                    local payloadTb, ok = json.decode(data.payload)
                    if ok == true then
                        -- 处理
                        handlePropSet(payloadTb)
                        -- 发送
                        -- 通过mqtt发送出去
                        local reTb = {
                            ["result_code"] = 0,
                            ["result_desc"] = "success"
                        }
                        mqttOutMsg.insertMsg2Json(
                            _G.MQTT_TOPIC_PROSET_REQ .. 'response/request_id=' ..
                                requestId, reTb, 0, {cb = hwpubCb})
                    end
                end
            end

            -- 平台查询设备属性
            -- {
            --    "object_device_id": "{object_device_id}",
            --    "service_id": "Temperature"
            -- }
            -- $oc/devices/{device_id}/sys/properties/get/request_id={request_id}
            if string.find(data.topic, _G.MQTT_TOPIC_PROSGET) then
                -- 以request_id 分割
                local arr, n = tool.strSplit(data.topic, 'request_id=')
                -- $oc/devices/{device_id}/sys/properties/set/response/request_id={request_id}
                if n == 2 and arr[1] == _G.MQTT_TOPIC_PROSGET then
                    local requestId = arr[2]
                    -- 真的是这个topic
                    local payloadTb, ok = json.decode(data.payload)
                    if ok == true then
                        -- 处理
                        local service_id, sbody = handlePropGet(payloadTb)
                        -- 发送
                        -- 通过mqtt发送出去
                        local reTb = {
                            ["services"] = {
                                [1] = {
                                    ["service_id"] = service_id,
                                    ["properties"] = sbody
                                }
                            }
                        }
                        mqttOutMsg.insertMsg2Json(
                            _G.MQTT_TOPIC_PROSGET .. 'response/request_id=' ..
                                requestId, reTb, 0, {cb = hwpubCb})
                    end
                end
            end

            -- 如果mqttOutMsg中有等待发送的数据，则立即退出本循环
            if mqttOutMsg.waitForSend() then return true end
            -- 马上break避免等下一个包才处理
            -- break
        else
            break
        end
    end

    return result or data == "timeout" or data == "APP_SOCKET_SEND_DATA"
end
